home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / packet / tcpip / amiga / asrc29k.lha / nrs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-08  |  5.0 KB  |  222 lines

  1. /* This module implements the serial line framing method used by
  2.  * net/rom nodes.  This allows the net/rom software to talk to
  3.  * an actual net/rom over its serial interface, which is useful
  4.  * if we want to do packet switching for multi-line wormholes.
  5.  * Dan Frank, W9NK
  6.  */
  7. #include <stdio.h>
  8. #include "global.h"
  9. #include "mbuf.h"
  10. #include "iface.h"
  11. #include "ax25.h"
  12. #include "nrs.h"
  13. #include "amiga/asy.h"
  14. #include "trace.h"
  15. #include "commands.h"
  16.  
  17. int Nnrs;
  18.  
  19. static struct mbuf *nrs_encode __ARGS((struct mbuf *bp));
  20. static struct mbuf *nrs_decode __ARGS((int dev,char c));
  21.  
  22. /* control structures, sort of overlayed on async control blocks */
  23. struct nrs Nrs[ASY_MAX];
  24.  
  25. /* Send a raw net/rom serial frame */
  26. int
  27. nrs_raw(iface,bp)
  28. struct iface *iface;
  29. struct mbuf *bp;
  30. {
  31.     struct mbuf *bp1;
  32.  
  33.     dump(iface,IF_TRACE_OUT,TYPE_AX25,bp) ;
  34.     
  35.     if((bp1 = nrs_encode(bp)) == NULLBUF){
  36.         free_p(bp);
  37.         return -1;
  38.     }
  39.     return Nrs[iface->xdev].send(iface->dev,bp1);
  40. }
  41.  
  42. /* Encode a packet in net/rom serial format */
  43. static struct mbuf *
  44. nrs_encode(bp)
  45. struct mbuf *bp;
  46. {
  47.     struct mbuf *lbp;    /* Mbuf containing line-ready packet */
  48.     register char *cp;
  49.     char c;
  50.     unsigned char csum = 0 ;
  51.  
  52.     /* Allocate output mbuf that's twice as long as the packet.
  53.      * This is a worst-case guess (consider a packet full of STX's!)
  54.      * Add five bytes for STX, ETX, checksum, and two nulls.
  55.      */
  56.     lbp = alloc_mbuf((int16)(2*len_p(bp) + 5));
  57.     if(lbp == NULLBUF){
  58.         /* No space; drop */
  59.         free_p(bp);
  60.         return NULLBUF;
  61.     }
  62.     cp = lbp->data;
  63.  
  64.     *cp++ = STX ;
  65.  
  66.     /* Copy input to output, escaping special characters */
  67.     while(pullup(&bp,&c,1) == 1){
  68.         switch(uchar(c)){
  69.         case STX:
  70.         case ETX:
  71.         case DLE:
  72.             *cp++ = DLE;
  73.             /* notice drop through to default */
  74.         default:
  75.             *cp++ = c;
  76.         }
  77.         csum += uchar(c) ;
  78.     }
  79.     *cp++ = ETX;
  80.     *cp++ = csum ;
  81.     *cp++ = NUL ;
  82.     *cp++ = NUL ;
  83.     
  84.     lbp->cnt = cp - lbp->data;
  85.     return lbp;
  86. }
  87. /* Process incoming bytes in net/rom serial format
  88.  * When a buffer is complete, return it; otherwise NULLBUF
  89.  */
  90. static struct mbuf *
  91. nrs_decode(dev,c)
  92. int dev;    /* net/rom unit number */
  93. char c;        /* Incoming character */
  94. {
  95.     struct mbuf *bp;
  96.     register struct nrs *sp;
  97.  
  98.     sp = &Nrs[dev];
  99.     switch(sp->state) {
  100.         case NRS_INTER:
  101.             if (uchar(c) == STX) {    /* look for start of frame */
  102.                 sp->state = NRS_INPACK ;    /* we're in a packet */
  103.                 sp->csum = 0 ;                /* reset checksum */
  104.             }
  105.             return NULLBUF ;
  106.         case NRS_CSUM:
  107.             bp = sp->rbp ;
  108.             sp->rbp = NULLBUF ;
  109.             sp->rcnt = 0 ;
  110.             sp->state = NRS_INTER ;    /* go back to inter-packet state */
  111.             if (sp->csum == uchar(c)) {
  112.                 sp->packets++ ;
  113.             } else {
  114.                 free_p(bp) ;    /* drop packet with bad checksum */
  115.                 bp = NULLBUF;
  116.                 sp->errors++ ;    /* increment error count */
  117.             }
  118.             return bp ;
  119.         case NRS_ESCAPE:
  120.             sp->state = NRS_INPACK ;    /* end of escape */
  121.             break ;            /* this will drop through to char processing */
  122.         case NRS_INPACK:
  123.             switch (uchar(c)) {
  124.             /* If we see an STX in a packet, assume that previous */
  125.             /* packet was trashed, and start a new packet */
  126.             case STX:
  127.                 free_p(sp->rbp) ;
  128.                 sp->rbp = NULLBUF ;
  129.                 sp->rcnt = 0 ;
  130.                 sp->csum = 0 ;
  131.                 sp->errors++ ;
  132.                 return NULLBUF ;
  133.             case ETX:
  134.                 sp->state = NRS_CSUM ;    /* look for checksum */
  135.                 return NULLBUF ;
  136.             case DLE:
  137.                 sp->state = NRS_ESCAPE ;
  138.                 return NULLBUF ;
  139.             }
  140.     }
  141.     /* If we get to here, it's with a character that's part of the packet.
  142.      * Make sure there's space for it.
  143.      */
  144.     if(sp->rbp == NULLBUF){
  145.         /* Allocate first mbuf for new packet */
  146.         if((sp->rbp1 = sp->rbp = alloc_mbuf(NRS_ALLOC)) == NULLBUF) {
  147.             sp->state = NRS_INTER ;
  148.             return NULLBUF; /* No memory, drop */
  149.         }
  150.         sp->rcp = sp->rbp->data;
  151.     } else if(sp->rbp1->cnt == NRS_ALLOC){
  152.         /* Current mbuf is full; link in another */
  153.         if((sp->rbp1->next = alloc_mbuf(NRS_ALLOC)) == NULLBUF){
  154.             /* No memory, drop whole thing */
  155.             free_p(sp->rbp);
  156.             sp->rbp = NULLBUF;
  157.             sp->rcnt = 0;
  158.             sp->state = NRS_INTER ;
  159.             return NULLBUF;
  160.         }
  161.         sp->rbp1 = sp->rbp1->next;
  162.         sp->rcp = sp->rbp1->data;
  163.     }
  164.     /* Store the character, increment fragment and total
  165.      * byte counts
  166.      */
  167.     *sp->rcp++ = c;
  168.     sp->rbp1->cnt++;
  169.     sp->rcnt++;
  170.     sp->csum += uchar(c) ;    /* add to checksum */
  171.     return NULLBUF;
  172. }
  173.  
  174. /* Process net/rom serial line I/O */
  175. void
  176. nrs_recv(dev,v1,v2)
  177. int dev;
  178. void *v1;
  179. void *v2;
  180. {
  181.     char c;
  182.     struct mbuf *bp,*nbp;
  183.     struct phdr *phdr;
  184.  
  185.     /* Process any pending input */
  186.     for(;;){
  187.         c = Nrs[dev].get(Nrs[dev].iface->dev);
  188.         if((bp = nrs_decode(dev,c)) == NULLBUF)
  189.             continue;
  190.         if((nbp = pushdown(bp,sizeof(struct phdr))) == NULLBUF){
  191.             free_p(bp);
  192.             continue;
  193.         }
  194.         phdr = (struct phdr *)nbp->data;
  195.         phdr->iface = Nrs[dev].iface;
  196.         phdr->type = TYPE_AX25;
  197.         enqueue(&Hopper,nbp);
  198.     }
  199.  
  200. }
  201. /* donrstat:  display status of active net/rom serial interfaces */
  202. int
  203. donrstat(argc,argv,p)
  204. int argc ;
  205. char *argv[] ;
  206. void *p;
  207. {
  208.     register struct nrs *np ;
  209.     register int i ;
  210.  
  211.     tprintf("Interface   RcvB  NumReceived  CSumErrors\n") ;
  212.  
  213.     for (i = 0, np = Nrs ; i < ASY_MAX ; i++, np++)
  214.         if (np->iface != NULLIF)
  215.             if(tprintf(" %8s   %4d   %10lu  %10lu\n",
  216.              np->iface->name, np->rcnt,
  217.              np->packets, np->errors) == EOF)
  218.                 break;
  219.  
  220.     return 0 ;
  221. }
  222.